/**
 * Created by Admin on 30.12.2014.
 */

var GlControl = (function ($) {

    return $.inherit({
        options: {
            onNoWebGl: $.noop,
            onRenderStarted: $.noop,
            onFpsCalculated: $.noop
        },

        gl: null,
        shaders: null,
        shaderControls: null,
        mouseControl: null,
        cameraControl: null,

        setViewPort: function (canvas) {
            this.gl.viewportWidth = canvas.width;
            this.gl.viewportHeight = canvas.height;
        },

        _initGl: function (canvas) {
            var glControl = this;
            try {
                glControl.gl = canvas.getContext("experimental-webgl"/*, {preserveDrawingBuffer: true}*/);
                glControl.setViewPort(canvas);
            } catch (e) {
                glControl.options.onNoWebGl();
            }
            if (!glControl.gl) {
                glControl.options.onNoWebGl();
            }
        },

        _initShaders: function (glShaderResources) {
            var glControl = this;
            var gl = glControl.gl;
            $.each(glShaderResources, function (shaderName, resource) {
                try {
                    var glShader = new GlShader(resource, gl);
                    if (shaderName != "click") {
                        glControl.shaders[shaderName] = glShader;
                        glControl.shaderControls[shaderName] = new GlShaderControl(glShader, gl);
                    } else {
                    }
                } catch (e) {
                    console.error(shaderName, e.message);
                }
            });
        },

        addObjectToShader: function (shader, sceneObject) {
            var objectId = this.currentObjectId;
            var cameraControl = this.cameraControl;
            this.mouseControl.addClickableObject(sceneObject.bind("mousedown", function (glObject) {
                cameraControl.selectedCamera = glObject.camera;
            }), objectId);
            sceneObject.setCamera(cameraControl.addCamera(objectId));
            this.shaderControls[shader.name].addObject(objectId, sceneObject);

            this.currentObjectId++;
        },

        addObjectsToShader: function (shader, sceneObjects) {
            var control = this;
            sceneObjects && $.each(sceneObjects, function (_, sceneObject) {
                sceneObject && control.addObjectToShader(shader, sceneObject);
            });
            return this;
        },

        setWindowViewPort: function (canvas) {
            canvas.setAttribute("width", window.innerWidth - 40);
            canvas.setAttribute("height", window.innerHeight - 40);
            this.setViewPort(canvas);
        },

        __constructor: function (canvas, options) {
            this.options = $.extend({}, this.options, options);
            this._initGl(canvas);
            this.currentObjectId = 0;
            this.fps = 0;
            var glControl = this;

            setInterval(function () {
                glControl.options.onFpsCalculated(glControl.fps)
                glControl.fps = 0;
            }, 1000);

            this.setWindowViewPort(canvas);

            $(window).resize(function () {
                glControl.setWindowViewPort(canvas);
            });

            glControl.shaders = {};
            glControl.shaderControls = {};
            var SIMPLE_SHADER = GlShader.COMMON_SHADERS.SIMPLE;
            var CLICK_SHADER = GlShader.COMMON_SHADERS.CLICK;
            var SURF_SHADER = GlShader.COMMON_SHADERS.SURF;
            new LoadingTree({
                shaders: {
                    queue: new LoadingTree({
                        simple: {
                            queue: new ShaderLoader(SIMPLE_SHADER),
                            metaData: SIMPLE_SHADER
                        },

                        click: {
                            queue: new ShaderLoader(CLICK_SHADER),
                            metaData: CLICK_SHADER
                        },

                        surf: {
                            queue: new ShaderLoader(SURF_SHADER),
                            metaData: SURF_SHADER
                        }
                    })
                }
            }).load(function (_, glOuterResources) {
                    var gl = glControl.gl;
                    glControl._initShaders(glOuterResources.shaders.result);
                    glControl.mouseControl = new GlMouseControl(gl, canvas, glControl.shaderControls);
                    glControl.cameraControl = new GlCameraControl(canvas);

                    gl.clearColor(0.0, 0.0, 0.0, 1.0);
                    gl.enable(gl.DEPTH_TEST);

                    glControl.render();
                    glControl.options.onRenderStarted();

                });
        },

        resetViewPort: function () {
            var gl = this.gl;
            gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        },

        render: function () {
            var glControl = this;
            requestAnimFrame(function () {
                glControl.render();
            });
            if (!this.mouseControl.isClick) {
                this.resetViewPort();
                $.each(this.shaderControls, function (_, shaderControl) {
                    shaderControl.render();
                });
            }
            this.fps++;
        }
    }, {})

})(window["jQuery"]);